package org.gordonframework.core.collection {
	import org.gordonframework.core.collection.GCollection;
	
	/**
	 * 
	 * A Set implementation of GCollection where each item
	 * is identified by a String id, enforced by the GItem interface.
	 * 
	 * @author eriarv
	 */
	public class GSet implements GCollection {
		
		private var items : Array = new Array();
		
		/**
		 * Adds an item to the set.
		 * 
		 * @param item - item to add
		 * @return true - if item added, false if item already present
		 */
		public function add(item : GItem) : Boolean {
			if ( contains( item ) ) {
				return false;
			} else {
				items.push( item );
				return true;
			}
		}
		
		public function addAll(collection : GCollection) : Boolean {
			var itemWasAdded : Boolean = false;
			for each ( var item : GItem in collection.toArray() ) {
				itemWasAdded = itemWasAdded || add(item );
			}
			return itemWasAdded;
		}
		
		public function addAndReplace( item : GItem ) : Boolean {
			if ( contains( item ) ) {
				remove( item );
			} 
			items.push( item );
			return true;
		}

		public function clear() : void {
			items = new Array();
		}
		
		public function contains(item : GItem) : Boolean {
			return containsItemWithId( item.id );
		}
		
		public function containsItemWithId( id : String ) : Boolean {
			return indexOfItemWithId(id) != -1;
		}
		
		public function getItemById( id : String ) : GItem {
			var i : int = indexOfItemWithId(id);
			if ( i != -1 ) {
				return items[i] as GItem;
			} else {
				return null;
			}
		}
		
		private function indexOfItem( item : GItem ) : int {
			return indexOfItemWithId(item.id);
		}
		
		private function indexOfItemWithId( id : String ) : int {
			var i : int = -1;
			items.some( 
				function (setItem:GItem, index:int, array:Array) : Boolean {
					if ( setItem.id == id ) {
						i = index;
						return true;
					} else {
						return false;
					}
				}
			);
			return i;
		}

		public function isEmpty() : Boolean {
			return size == 0;
		}
		
		public function remove(item : GItem) : Boolean {
			var i : int = indexOfItem(item);
			if ( i != -1 ) {
				items.splice( i, 1 );
				return true;
			} else {
				return false;
			}
		}
		
		
		
		public function toArray() : Array {
			return items;
		}
		
		public function get size() : int {
			return items.length;
		}
	}
}
